package com.baixiaowen.xiaoaointerview.大厂笔试_白板面试篇.解读反射_代理_AOP.proxy;

import com.baixiaowen.xiaoaointerview.大厂笔试_白板面试篇.basic.monad.Try;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public interface Aspect {

    void before();

    void after();

    static <T> T getProxy(Class<T> cls, String ... aspects) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        List<Try<Aspect>> aspectInsts = Arrays.stream(aspects).map(name -> Try.ofFailable(() -> {
            Class clazz = Class.forName(name);
            return (Aspect) clazz.getConstructor().newInstance();
        }))
                .filter(aspect -> aspect.isSuccess())
                .collect(Collectors.toList());

        T inst = cls.getConstructor().newInstance();

        return (T) Proxy.newProxyInstance(
                cls.getClassLoader(),
                cls.getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        for (Try<Aspect> aspect : aspectInsts) {
                            aspect.get().before();
                        }

                        Object result = method.invoke(inst);

                        for (Try<Aspect> aspect : aspectInsts) {
                            aspect.get().after();
                        }
                        return result;
                    }
                }
        );
    }

}
